Repository navigation
feat!: report what a text should be refused for, move to TypeScript, ESM, vite and vitest - #161
Merged
Merged
Conversation
- `forbidden(text)` lists the links and phone numbers a text should be refused
for. It relies on a strict detection, apart from the one used to censor: a
false positive there rejects an honest text instead of adding a few stars.
- every match gets a `type` (link, email, phone), and exceptions can be given
by type.
- a link written without scheme on an unknown TLD (evil.cfd/a/x) is now
censored too; the censoring of phone numbers is unchanged.
- the package gets an ESM entry, so that a default import gives the class
under Node ESM. `require('censorify-it').default` still works.
BREAKING CHANGE: the package now has an `exports` map, deep imports of its
files are no longer possible.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The source becomes a TypeScript class extending LinkifyIt, built with vite as
an ES module with a CommonJS build and its types. Tests run with vitest, lint
with the flat config of eslint-config-vizeat, and commits go through husky,
lint-staged and commitlint, as in our other packages.
The CI workflow is rewritten: the previous one relied on deprecated actions
and failed before running anything. It now lints, checks types, builds, loads
the package both ways, and tests with coverage on Node 24.
linkify-it stays on v3: v6 changes its defaults (links without a scheme are
no longer found), which would change what is censored.
BREAKING CHANGE: the package is an ES module with an `exports` map. Its files
moved to dist/censorify-it.js and dist/censorify-it.cjs, and deep imports are
no longer possible. `require('censorify-it').default` still gives the class.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
albanv
force-pushed
the
feat/strict-matches
branch
from
November 12, 2026 11:15
71bb426 to
a985400
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #161 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 1
Lines 50 70 +20
Branches 11 22 +11
=========================================
+ Hits 50 70 +20 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
`forbidden` and `matchStrict` never report an email: their matches are now typed 'link' | 'phone', so a caller branching on the type does not have to handle a case that cannot happen. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
linkify-it goes from 3 to 5. What is censored does not change, except for a
trailing punctuation mark or closing bracket that is no longer swallowed.
It does not go to 6, which no longer finds an email written right after a
label ("email:john@example.com") nor a domain with a port ("evil.com:8080").
A test now holds these two cases.
TypeScript goes to 6, not 7: vite-plugin-dts needs the JavaScript compiler
API. vitest goes to 5, commitlint to 21, lint-staged to 17.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
mm22dev
approved these changes
Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four commits: the feature, the move of the package to our current tooling, the update of its dependencies, and a typing fix found while plugging a TypeScript caller onto the built package (the matches of
forbiddenare typedlinkorphone, neveremail).1. Report what a text should be refused for
Why
censorify-it finds links, emails and phone numbers to censor them. We also want to refuse a text that holds a link or a phone number, at the time it is written. The same package should answer both, so that what is refused and what is censored do not drift apart.
The existing detection cannot be reused as is for refusing. It is tuned to censor, where a false positive only costs a few stars:
evil.cfd/a/x(no scheme, unknown TLD)see you soon.In any casesoon.In, as a linkgroup of 12 15 20 25 people12 15 20 25, as a phone numberWhat
forbidden(text)lists the links and phone numbers a text should be refused for, exceptions applied. It relies on a strict detection, kept apart from the one used to censor:scheme://,www.,domain/pathordomain?query, whatever the TLD. A bare domain is not reported;type:link,emailorphone.set({ exceptions: { link: [...], phone: [...] } }). A single list still works. By type is safer: a loose phone number pattern in a single list also lets through the links holding these digits.evil.cfd?mysite.com/xis one link to evil.cfd). The censoring of phone numbers and emails is unchanged: the six existing tests pass untouched.Everything
forbiddenreports is censored byprocessas well; a test holds that property.Known limits of the strict detection
+(they look like a date), numbers spelled out or split with slashes, obfuscated links (evil . com).150.00-200.00.2. TypeScript, ES modules, vite and vitest
CensorifyIt,Match,Options,Exceptions...).dist/censorify-it.jsanddist/censorify-it.cjs. The class is the default export and a named one. Until now a default import under Node ESM gave the module object, andnew CensorifyIt()threw.eslint-config-vizeat, husky, lint-staged and commitlint. babel is gone.importandrequire), and tests with coverage, on Node 24.email:john@example.com) nor a domain with a port (evil.com:8080); a test holds these two cases, so the Renovate PR for v6 will fail. TypeScript goes to 6, not 7 (vite-plugin-dts needs the JavaScript compiler API), vitest to 5, commitlint to 21, lint-staged to 17.Breaking changes
Version 4.0.0:
exportsmap: its files moved, and deep imports are no longer possible;require('censorify-it').defaultstill gives the class.The API is otherwise only extended.
Tests
51 tests pass (6 existing, 45 new), lint and type check pass. The built package was loaded both ways under Node, and the test suite of a TypeScript ESM project depending on it passes against the local build.
To check on this repository
CODECOV_TOKENmust exist in the repository secrets for the coverage upload.yarn pub, to the public npm registry.🤖 Generated with Claude Code